/*
 * CS_QUICK_MATCH_PLAYER.cpp
 *
 *  Created on: 2013. 9. 24.
 *      Author: mega@gamevil.com
 */

#include "../../Command.h"

#include "../../User.h"
#include "../../Proxy.h"
#include "../../NLogic/Space.h"
#include "../../NLogic/Static.h"
#include "../../NLogic/SocialInfo.h"

namespace ProjectZ { namespace NCommand {

void SendFailPVPQuickMatch(User * pUser, int res)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(res);
	pAck->MakePacket(CMD_SC_QUICK_MATCH_PLAYER);
	pUser->Send(pAck);
	return;
}

void Command::CS_QUICK_MATCH_PLAYER(User * pUser, ::Network::Packet * pPacket)
{
	PREPARE_PACKET;

	NLogic::Space * pSpace = pUser->GetSpace();
	if (NULL == pSpace)
	{
		DEBUGLOG("CS_QUICK_MATCH_PLAYER : pSpace is NULL!!");
		return;
	}

//	if (false == pUser->EndBattle_afterEffect())
//	{
//		SendFailPVPQuickMatch(pUser, ACK_BATTLE_AFTEREFFECT);
//		return;
//	}

	if (pUser->GetEnumState() != User::EnumState::__NONE__)
	{
		SendFailPVPQuickMatch(pUser, ACK_MATCHING_FAIL);
		DEBUGLOG("CS_QUICK_MATCH_PLAYER : pUser->GetEnumState() != User::EnumState::__NONE__");
		return;
	}


	int minLevel = 0;
	int maxLevel = 0;

	// 5연승 이상인 경우 대전상대 레벨 범위 (0 ~ n)
	if (pUser->GetCharacterInfo().consecutive_win >= 5)
	{
		minLevel = pUser->GetCharacterInfo().level;
		maxLevel = pUser->GetCharacterInfo().level;

		if (pUser->GetCharacterInfo().consecutive_win >= 9)
			maxLevel += 9;
		else
			maxLevel += pUser->GetCharacterInfo().consecutive_win;
	}
	// 5연승 미만인 경우 대전상대 레벨 범위 (-9 + n ~ n)
	else
	{
		minLevel = pUser->GetCharacterInfo().level + (pUser->GetCharacterInfo().consecutive_win - 9);
		maxLevel = pUser->GetCharacterInfo().level + pUser->GetCharacterInfo().consecutive_win;

		if (minLevel < 0)
			minLevel = 1;
	}

	std::vector<User *> oppUserVector;
	oppUserVector.clear();

	auto iter = NProxy::GetUserTree().begin();
	for (; iter != NProxy::GetUserTree().end(); ++iter)
	{
		if (iter->second == pUser)
			continue;

		NLogic::Space * pSpaceTemp = iter->second->GetSpace();
		if (NULL == pSpaceTemp)
		{
			DEBUGLOG("CS_QUICK_MATCH_PLAYER : pSpaceTemp is NULL!!");
			continue;
		}

		NLogic::SocialInfo * pSocialInfo = iter->second->GetSocialInfo();
		if (NULL == pSocialInfo)
		{
			DEBUGLOG("CS_QUICK_MATCH_PLAYER : pSocialInfo is NULL!!");
			continue;
		}

		if (pSpaceTemp->GetData()._spaceType != NLogic::Space::SpaceType::WORLD)
			continue;

		if (iter->second->GetEnumState() != User::EnumState::__NONE__)
			continue;

		// PVP 신청 차단 유저는 매칭하지 않는다
		if (!(pSocialInfo->GetData()->_invite_blocked & static_cast<int>(NLogic::SocialInfo::EnumInviteState::PVP_ON)))
			continue;

		// 레벨 범위 검사
		if (static_cast<int>(iter->second->GetCharacterInfo().level) < minLevel)
			continue;

		if (static_cast<int>(iter->second->GetCharacterInfo().level) > maxLevel)
			continue;

		oppUserVector.push_back(iter->second);
	}

	int vectorSize = static_cast<int>(oppUserVector.size());

	if (0 >= vectorSize)
	{
		DEBUGLOG("CS_QUICK_MATCH_PLAYER : oppUserVector Size is ZERO!!");
		SendFailPVPQuickMatch(pUser, ACK_MATCHING_FAIL);
		return;
	}

	User * pOppUser = oppUserVector[rand() % vectorSize];
	if (NULL == pOppUser)
	{
		DEBUGLOG("CS_QUICK_MATCH_PLAYER : pOppUser is NULL!!");
		SendFailPVPQuickMatch(pUser, ACK_MATCHING_FAIL);
		return;
	}

	// Party 생성
	NLogic::Party * pParty = NLogic::Static::Instance().GETPARTYPOOL()->NEW();
	pParty->Open(pUser);
	pParty->EnterUser(pOppUser);

	// PVP Space생성
	NLogic::Space::Data clsData;
	clsData._maxUser = 2;
	clsData._spaceType = NLogic::Space::SpaceType::PVP_USER;

	NLogic::Space * pPVPSpace = NLogic::Static::Instance().GETSPACEPOOL()->NEW();
	pPVPSpace->Open(pUser, clsData);
	pPVPSpace->SetParty(pParty);

	// 방장 입장
	pSpace->LeaveUser(pUser);
	pPVPSpace->EnterUser(pUser);

	// 응답
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << pUser->GetUserSeq();
	*pAck << static_cast<char>(2);	// 랜덤대전
	*pAck << static_cast<int>(-1);		// 파티 Seq (사용안함)
	pAck->MakePacket(CMD_SC_PVP_MATCH_ASK);
	pOppUser->Send(pAck);

	// 유저의 상태 변경
	pUser->SetEnumState(User::EnumState::PVP_QUICK_WAIT);
	pOppUser->SetEnumState(User::EnumState::PVP_QUICK_WAIT);

	// 파티 상태 변경
	pParty->SetState(NLogic::Party::State::PVP_ACCEPT_WAIT);
}

} /*NCommand*/ } /*ProjectZ*/
